/*!
 * @file opp_con.c
 * @brief OPP Connection processing
 * @par Copyright (C) 2008 ALPS ELECTRIC CO., LTD
 */
 
/****************************************************************************
 * Includes
 ****************************************************************************/
#include "../alps_app/private.h"

/*!
 * @brief 
 * 
 * 
 * 
 * 
 */

void oppConnectResult(param_data* param)
{
	uint8 status, length;
	bdaddr bd_addr;
	uint8* name = 0;
	
	paramGet8bitVal(param, &status);//status
	paramGetDataVal(param, bd_addr, BD_ADDR_LENGTH);
	reverseBdaddrData((uint8*)bd_addr);
	app.opp.opp_limit_con = 0;
	
	if(0 == status )
	{
		if(oppReady == app.opp.opp_state)
		{
			//set opp state as busy, reset state as ready in case of connection attempt fail or disconnected.
			oppUpdateState(oppBusy);
		}
		status = EVTRES_SUCCESS;
	}
	else if(0x8E == status)
	{
		 if(0 == handleACLProcess(aclUpdateRole, bd_addr, roleSlave))
		 {
			status = EVTRES_RESTRICTED_CONNECTION;
			app.opp.opp_limit_con = 1;
			paramGet8bitVal(param, &length);
			app.name_length = length;
			if(app.name_length)
			{
				memcpy(app.device_name,&param->data[param->index],app.name_length);
			}

			return;
		 }
		 else
		 {
		 		if(oppReady == app.opp.opp_state)
				{
					//set opp state as busy, reset state as ready in case of connection attempt fail or disconnected.
					oppUpdateState(oppBusy);
				}
				status = EVTRES_SUCCESS;
		 }
	}
	else
	{/*! @todo updated status according tsb status*/
		status = EVTRES_OPERATION_FAIL;
	}
	
	paramGet8bitVal(param, &length);
	if(length)
	{
		name = &param->data[param->index];
	}
	evtConnectResult(status, bd_addr, HOST_SRV_OPP, 0, length, name);
}

/*!
 * @brief 
 * 
 * 
 * 
 * 
 */

void oppDisconnectResult(param_data* param)
{
	bdaddr bd_addr;
	uint8 illegaladdr[6]={0xff,0xff,0xff,0xff,0xff,0xff};
	
	paramGetDataVal(param, bd_addr, BD_ADDR_LENGTH);
	
	//used for process "no abort event"
	if(OPP_IN_TRANSFER == app.opp.opp_status)
	{
		genericHostMsg(HOST_OPPS_PUSH_COMP_IND, EVTRES_ABORTED);
		app.opp.opp_status = OPP_NO_TRANSFER;
	}
			
	oppUpdateState(oppReady);//after disconnect current status is ready.

	if(1 == app.opp.opp_limit_con)
	{
		evtConnectResult(EVTRES_RESTRICTED_CONNECTION, bd_addr, HOST_SRV_OPP, 0, app.name_length, app.device_name);
		return;
	}
	if(0 == memcmp(bd_addr,illegaladdr, BD_ADDR_LENGTH))//toshiba return all F value. 
	{
		evtDisconnectResult(EVTRES_ILLEGAL_STATE, HOST_SRV_OPP);
	}
	else
	{
		evtDisconnectResult(EVTRES_SUCCESS, HOST_SRV_OPP);
	}

}

void evtOPPPushRequest(param_data* param)
{
	uint16 opcode = HOST_OPPS_PUSH_HEADER_IND;
	param_data data, bodydata;//parameter data
	UCHAR buffer[642];/*! @TODO check here */
	uint8 permission,type;//,data_continue;
	uint16 namelength,bodylen;
	uint32 totalbodylen;
	stack_msg msg;
	char namesuffix[8];
	char lownamesuffix[4];

	data.data = buffer;
	data.index = 0;
	data.param_len = 0;

	//judge oppBusy is for avoid comming  request event after disconnect 
	if((oppBusy != app.opp.opp_state) && (0 == app.opp.opp_limit_con))
		return;
	
	paramGet8bitVal(param, &permission);

	//get header information of data.
	paramGet8bitVal(param, &type);
	
	paramGetTSB16bitVal(param, &namelength);

	/* get type via object name*/
	if(namelength >= 4)
	{	
		uint8 i;
		memcpy(namesuffix,&param->data[param->index+namelength-8],8);
		for(i=0;i<4;i++){
			//convert upper char to lower char
			if(64 < namesuffix[i*2+1] && namesuffix[i*2+1] < 91)
				lownamesuffix[i]=(char)(namesuffix[i*2+1]+32);
			else
				lownamesuffix[i]=(char)(namesuffix[i*2+1]);
		}
		
		if(memcmp(lownamesuffix,".vcf",4) == 0 )
			type = 0x01;
		else if(memcmp(lownamesuffix,".vcs",4) == 0)
			type = 0x02;
		else if(memcmp(lownamesuffix,".vmg",4) == 0)
			type = 0x03;
		else if(memcmp(lownamesuffix,".vnt",4) == 0)
			type = 0x04;
	}
	
	paramSet8bitVal(&data,type);
	
	paramSet16bitVal(&data,namelength);
	paramSetDataVal(&data,&param->data[param->index], namelength);
	
	
	paramSkipNByte(param,namelength);

	paramGetTSB32bitVal(param, &totalbodylen);
	/* if the first packet and totallen is zero,then directly send data request command to toshiba */
	if(0x01 == permission)
	{
		app.opp.opp_ifheader = 1; // To be moved to other place
		createStackMsg(TSB_OPP, TCU_OPP_SVR_PUSH_RESPONSE_REQ, &msg);
		if(1 == app.opp.opp_limit_con)
			msgSet8bitVal(&msg, 0x00);
		else
			msgSet8bitVal(&msg, 0xa0);
		if( 0x00 == totalbodylen)
		{
			sendStackMessage(&msg);
			return;
		}
		else
		{
			sendStackMessage(&msg);
		}
	}
	paramSet32bitVal(&data,totalbodylen);
	/* judge if header */
	if (1 == app.opp.opp_ifheader)
	{
		sendUartMsg(opcode, &data);
		app.opp.opp_ifheader = 0;
	}

	//process body
	memset(buffer,0x00,642);
	bodydata.data = buffer;
	bodydata.index = 0;
	bodydata.param_len = 0;

	paramGetTSB16bitVal(param, &bodylen);
	paramSet16bitVal(&bodydata, bodylen);
	paramSetDataVal(&bodydata, &param->data[param->index],bodylen);
	paramSkipNByte(param,bodylen);
	paramGet8bitVal(param, &app.opp.data_continue);
	app.opp.opp_status = OPP_IN_TRANSFER;
	sendUartMsg(HOST_OPPS_PUSH_BODY_IND, &bodydata);

	if(0x00 == app.opp.data_continue)
	{
		genericHostMsg(HOST_OPPS_PUSH_COMP_IND, EVTRES_SUCCESS);
		app.opp.opp_status = OPP_NO_TRANSFER;
	}
}

/*!
 * @brief opp flow control during data transfer.
 * 
 * @param fc flow-control operation 0-go, non-0 stop data transfer.
 * 
 * @return process result
 */
void reqOppFlowControl(param_data* param)
{
	stack_msg	msg;
	uint8		fc;
	uint8		res=0;
	
	res |= paramGet8bitVal(param, &fc);
	if(res)
	{
		genericHostMsg(HOST_OPPS_FLOW_CTRL_REQ, EVTRES_ILLEGAL_FORMAT);
		return;
	}

	if(fc>1)
	{
		genericHostMsg(HOST_OPPS_FLOW_CTRL_REQ, EVTRES_ILLEGAL_PARAM);
		return;
	}	
	createStackMsg(TSB_OPP, TCU_OPP_SVR_FC_SETTING_REQ, &msg);
	msgSet8bitVal(&msg, fc);
	sendStackMessage(&msg);
}

void resOppFlowControl(param_data* param)
{
	uint8 status;

	paramGet8bitVal(param, &status);
	//in fact,send HOST_OPPS_FLOW_CTRL_CFM to host;
	if(0 == status)
	{
		genericHostMsg(HOST_OPPS_FLOW_CTRL_REQ, EVTRES_SUCCESS);
	}
	else
	{
		genericHostMsg(HOST_OPPS_FLOW_CTRL_REQ, EVTRES_ILLEGAL_STATE);
	}
}

/*!
 * @brief Abort opp operation
 * call by oppHostHandler when received DATA_RES with reject.
 * 
 * @return process result
 */
void reqOppAbort(void)
{
	stack_msg msg;
	
	createStackMsg(TSB_OPP, TCU_OPP_SVR_PUSH_ABORT_REQ, &msg);
	sendStackMessage(&msg);
}
void cfmOppAbort(uint8 status)
{
	if(0 != status)
	{
		genericHostMsg(HOST_OPPS_ABORT_REQ, EVTRES_OPERATION_FAIL);
	}
}

void evtOPPPushAbort(void)
{
	if(HOST_OPPS_ABORT_REQ == app.host_req)
	{
		genericHostMsg(HOST_OPPS_ABORT_REQ, EVTRES_SUCCESS);
	}
	if(OPP_IN_TRANSFER == app.opp.opp_status)
	{
		genericHostMsg(HOST_OPPS_PUSH_COMP_IND, EVTRES_ABORTED);
	}
	app.opp.opp_status = OPP_NO_TRANSFER;
}

